
#include "main_container.h"
#include "semantics_model.h"
#include "semantics_method.h"
#include "semantic_analyzer.h"
extern MainContainer * CompilerData;

SemanticsModel::SemanticsModel()
{
	this->CurrentContext = -1;

	this->ModifierPrivate = false;
	this->ModifierPublic = false;

	this->HasDefaultInLabel = false;
	this->HasDefaultOutLabel = false;

	this->Name = new GenericTable<int>();
	this->Parameters = new GenericTable<SemanticsMethodParameter>();

	this->LabelsIn = new GenericTable<int>();
	this->LabelsOut = new GenericTable<int>();

	this->Definition = new SemanticsModelBodyDefine();
	this->Structure = new SemanticsModelStructure();
}


SemanticsModel::~SemanticsModel()
{
	if(Name != NULL)
	{
		delete Name;
		Name = NULL;
	}

	if(Parameters != NULL)
	{
		delete Parameters;
		Parameters = NULL;
	}

	if(LabelsIn != NULL)
	{
		delete LabelsIn;
		LabelsIn = NULL;
	}

	if(LabelsOut != NULL)
	{
		delete LabelsOut;
		LabelsOut = NULL;
	}

	if(Definition != NULL)
	{
		delete Definition;
		Definition = NULL;
	}

	if(Structure != NULL)
	{
		delete Structure;
		Structure = NULL;
	}
}


#ifdef DEBUG
void SemanticsModelBodyDefine::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsModelBodyDefine>\n");

	// make output of table Fields
	fprintf(fo, "<semanticsFields>\n");
	for(int i = 0; i < this->Fields->GetCount(); i++)
	{
		SemanticsField * data = this->Fields->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</semanticsFields>\n");

	// make output of table Properties
	fprintf(fo, "<semanticsPropertys>\n");
	for(int i = 0; i < this->Properties->GetCount(); i++)
	{
		SemanticsProperty * data = this->Properties->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</semanticsPropertys>\n");

	// make output of table Enums
	fprintf(fo, "<semanticsEnums>\n");
	for(int i = 0; i < this->Enums->GetCount(); i++)
	{
		SemanticsEnum * data = this->Enums->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</semanticsEnums>\n");

	// make output of table Methods
	fprintf(fo, "<semanticsMethods>\n");
	for(int i = 0; i < this->Methods->GetCount(); i++)
	{
		SemanticsMethod * data = this->Methods->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</semanticsMethods>\n");

	fprintf(fo, "</semanticsModelBodyDefine>\n");

}
#endif


#ifdef DEBUG
void SemanticsModelBlock::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsModelBlock blockType=\"");

	// write BlockType
	switch (this->BlockType)
	{

	case ModBlockGenerate:
		fprintf(fo, "ModBlockGenerate");
		break;
	case ModBlockTerminate:
		fprintf(fo, "ModBlockTerminate");
		break;
	case ModBlockAdvance:
		fprintf(fo, "ModBlockAdvance");
		break;
	case ModBlockEnter:
		fprintf(fo, "ModBlockEnter");
		break;
	case ModBlockLeave:
		fprintf(fo, "ModBlockLeave");
		break;
	case ModBlockSeize:
		fprintf(fo, "ModBlockSeize");
		break;
	case ModBlockRelease:
		fprintf(fo, "ModBlockRelease");
		break;
	case ModBlockInqueue:
		fprintf(fo, "ModBlockInqueue");
		break;
	case ModBlockOutqueue:
		fprintf(fo, "ModBlockOutqueue");
		break;
	case ModBlockArrive:
		fprintf(fo, "ModBlockArrive");
		break;
	case ModBlockDepart:
		fprintf(fo, "ModBlockDepart");
		break;
	case ModBlockModelInstance:
		fprintf(fo, "ModBlockModelInstance");
		break;
	case ModBlockGoto:
		fprintf(fo, "ModBlockGoto");
		break;
	case ModBlockIf:
		fprintf(fo, "ModBlockIf");
		break;
	case ModBlockWait:
		fprintf(fo, "ModBlockWait");
		break;
	case ModBlockJoinGroup:
		fprintf(fo, "ModBlockJoinGroup");
		break;
	case ModBlockLeaveGroup:
		fprintf(fo, "ModBlockLeaveGroup");
		break;
	case ModBlockCreate:
		fprintf(fo, "ModBlockCreate");
		break;
	case ModBlockSplit:
		fprintf(fo, "ModBlockSplit");
		break;
	case ModBlockGather:
		fprintf(fo, "ModBlockGather");
		break;
	case ModBlockExecute:
		fprintf(fo, "ModBlockExecute");
		break;
	}

	fprintf(fo, "\" labels=\"");
	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->Labels, CompilerData->Units);
	fprintf(fo, "\">\n");

	fprintf(fo, "</semanticsModelBlock>\n");
}
#endif


#ifdef DEBUG
void SemanticsModelStructure::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsModelStructure>\n");

	// make output of table Blocks
	fprintf(fo, "<semanticsModelBlocks>\n");
	for(int i = 0; i < this->Blocks->GetCount(); i++)
	{
		SemanticsModelBlock * data = this->Blocks->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</semanticsModelBlocks>\n");

	fprintf(fo, "</semanticsModelStructure>\n");

}
#endif



#ifdef DEBUG
void SemanticsBlockTransactionDetail::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockTransactionDetail transactionName=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->TransactionName, CompilerData->Units);
	fprintf(fo, "\">\n");

	this->Expression->DebugXMLOutput(fo);


	fprintf(fo, "</semanticsBlockTransactionDetail>\n");


}
#endif




#ifdef DEBUG
void SemanticsBlockGenerate::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockGenerate transactionName=\"");
	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->TransactionName, CompilerData->Units);
	fprintf(fo, "\" />\n");

	// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->UptoExpression->DebugXMLOutput("uptoExpression", fo);


	// make output of table Blocks
	fprintf(fo, "<transactionList>\n");
	for(int i = 0; i < this->TransactionList->GetCount(); i++)
	{
		SemanticsBlockTransactionDetail * data = this->TransactionList->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</transactionList>\n");

	this->AfterExpression->DebugXMLOutput("afterExpression", fo);
	this->EveryExpressionMean->DebugXMLOutput("everyExpressionMean", fo);
	this->EveryExpressionDeviation->DebugXMLOutput("everyExpressionDeviation", fo);

	fprintf(fo, "</semanticsBlockGenerate>\n");

}
#endif


#ifdef DEBUG
void SemanticsBlockTerminate::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockTerminate>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockTerminate>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockAdvance::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockAdvance>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->ExpressionMean->DebugXMLOutput("expressionMean", fo);
	this->ExpressionDeviation->DebugXMLOutput("expressionDeviation", fo);

	fprintf(fo, "</semanticsBlockAdvance>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockEnter::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockEnter>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->ExpressionUnitsIn->DebugXMLOutput("expressionUnitsIn", fo);
	this->Expression->DebugXMLOutput(fo);
	this->ExpressionForming->DebugXMLOutput("expressionForming", fo);

	fprintf(fo, "</semanticsBlockEnter>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockLeave::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockLeave>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->ExpressionUnitsFrom->DebugXMLOutput("expressionUnitsFrom", fo);
	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockLeave>\n");
}
#endif

#ifdef DEBUG
void SemanticsBlockSeize::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockSeize>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);
	this->ExpressionForming->DebugXMLOutput("expressionForming", fo);

	fprintf(fo, "</semanticsBlockSeize>\n");
}
#endif

#ifdef DEBUG
void SemanticsBlockRelease::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockRelease>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockRelease>\n");
}
#endif

#ifdef DEBUG
void SemanticsBlockInqueue::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockInqueue>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockInqueue>\n");

}
#endif

#ifdef DEBUG
void SemanticsBlockOutqueue::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockOutqueue>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockOutqueue>\n");

}
#endif

#ifdef DEBUG
void SemanticsBlockArrive::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockArrive>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockArrive>\n");

}
#endif

#ifdef DEBUG
void SemanticsBlockDepart::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockDepart>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockDepart>\n");

}
#endif


#ifdef DEBUG
void SemanticsBlockModelInstance::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockModelInstance name=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->Name, CompilerData->Units);
	fprintf(fo, "\">\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	// make output of table Arguments
	fprintf(fo, "<arguments>\n");
	for(int i = 0; i < this->Arguments->GetCount(); i++)
	{
		SemanticsExpression * data = this->Arguments->GetData(i);
		data->DebugXMLOutput("argument", fo);
	}
	fprintf(fo, "</arguments>\n");

	// end tag
	fprintf(fo, "</semanticsBlockModelInstance>\n");
}
#endif



#ifdef DEBUG
void SemanticsBlockGoto::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockGoto label=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->Label, CompilerData->Units);
	fprintf(fo, "\">\n");

	// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	// end tag
	fprintf(fo, "</semanticsBlockGoto>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockIf::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockIf>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);
	this->StructureIf->DebugXMLOutput(fo);
	this->StructureElse->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockIf>\n");

}
#endif

#ifdef DEBUG
void SemanticsModelName::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsModelName name=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->Name, CompilerData->Units);
	fprintf(fo, "\">\n");

	// end tag
	fprintf(fo, "</semanticsModelName>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockWait::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockWait waitType=\">\n");

	// write wait type in attribute
	if (this->Type == WaitWhile)
		fprintf(fo, "WaitWhile");
	else
		fprintf(fo, "WaitUntil");
	fprintf(fo, "\">\n");

	// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->ExpressionForming->DebugXMLOutput("expressionForming", fo);


	// make output of table SensitivityList
	fprintf(fo, "<sensitivityList>\n");
	for(int i = 0; i < this->SensitivityList->GetCount(); i++)
	{
		SemanticsModelName * data = this->SensitivityList->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</sensitivityList>\n");

	this->ExpressionWhileUntil->DebugXMLOutput("expressionWhileUntil", fo);

	this->StructureThen->DebugXMLOutput(fo);
	this->StructureElse->DebugXMLOutput(fo);

	this->ExpressionTimeout->DebugXMLOutput("expressionTimeout", fo);
	this->StructureTimeout->DebugXMLOutput(fo);


	fprintf(fo, "</semanticsBlockWait>\n");

}
#endif



#ifdef DEBUG
void SemanticsBlockJoinGroup::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockJoinGroup>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockJoinGroup>\n");

}
#endif


#ifdef DEBUG
void SemanticsBlockLeaveGroup::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockLeaveGroup>\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsBlockLeaveGroup>\n");

}
#endif

#ifdef DEBUG
void SemanticsBlockCreate::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockCreate transactionName=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->TransactionName, CompilerData->Units);

	fprintf(fo, "\" sendToName=\"");
	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->SendToName, CompilerData->Units);
	fprintf(fo, "\">\n");

	// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->UptoExpression->DebugXMLOutput("uptoExpression", fo);

	this->AfterExpression->DebugXMLOutput("afterExpression", fo);
	this->EveryExpressionMean->DebugXMLOutput("everyExpressionMean", fo);
	this->EveryExpressionDeviation->DebugXMLOutput("EveryExpressionDeviation", fo);

	// make output of table TransactionList
	fprintf(fo, "<transactionList>\n");
	for(int i = 0; i < this->TransactionList->GetCount(); i++)
	{
		SemanticsBlockTransactionDetail * data = this->TransactionList->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</transactionList>\n");


	// end tag
	fprintf(fo, "</semanticsBlockCreate>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockSplit::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockSplit sendToName=\"");

	// name inside starting tag
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->SendToName, CompilerData->Units);
	fprintf(fo, "\">\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->ExpressionInto->DebugXMLOutput("ExpressionInto", fo);

	// end tag
	fprintf(fo, "</semanticsBlockSplit>\n");
}
#endif



#ifdef DEBUG
void SemanticsBlockGather::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockGather destroy=\"");
	if (this->Destroy)
		fprintf(fo, "true");
	else
		fprintf(fo, "false");
	fprintf(fo, "\">\n");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Expression->DebugXMLOutput(fo);

	// end tag
	fprintf(fo, "</semanticsBlockGather>\n");
}
#endif


#ifdef DEBUG
void SemanticsBlockExecute::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsBlockExecute>");

		// call base 
	SemanticsModelBlock::DebugXMLOutput(fo);

	this->Body->DebugXMLOutput(fo);

	// end tag
	fprintf(fo, "</semanticsBlockExecute>\n");
}
#endif



#ifdef DEBUG
void SemanticsModel::DebugXMLOutput(FILE * fo)
{
	fprintf(fo, "<semanticsModel name=\"");
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->Name, CompilerData->Units);

	fprintf(fo, "\" currentContext=\"");
	fprintf(fo, "%d", this->CurrentContext);

	fprintf(fo, "\" modifierPrivate=\"");
	if (this->ModifierPrivate)
		fprintf(fo, "true");
	else
		fprintf(fo, "false");

	fprintf(fo, "\" modifierPublic=\"");
	if (this->ModifierPublic)
		fprintf(fo, "true");
	else
		fprintf(fo, "false");

	fprintf(fo, "\" labelsIn=\"");
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->LabelsIn, CompilerData->Units);
	fprintf(fo, "\" labelsOut=\"");
	SemanticAnalyzer::DebugOutputNameFromTable(fo, this->LabelsOut, CompilerData->Units);
	fprintf(fo, "\">\n");

	// make output of table Parameters
	fprintf(fo, "<parameters>\n");
	for(int i = 0; i < this->Parameters->GetCount(); i++)
	{
		SemanticsMethodParameter * data = this->Parameters->GetData(i);
		data->DebugXMLOutput(fo);
	}
	fprintf(fo, "</parameters>\n");


	this->Definition->DebugXMLOutput(fo);
	this->Structure->DebugXMLOutput(fo);

	fprintf(fo, "</semanticsModel>\n");

}
#endif